这篇教程将教大家如何创建一个真实模拟LCD显示器外观和感觉的着色器。游戏《Slime Rancher》中有一个奇妙的化妆品特效就是用特殊的LCD着色器实现的,而且当接近监视器的时候,看起来就是像素化的效果。
LCD特效由几种不同的表现形式组成:
像素化效果。在屏幕上出现原始图片的像素化效果。
LCD渲染。每个像素都是由较小的R、G、B单元组成,其中的有效分量会影响像素的整体颜色 。
放大效果。这个效果只有靠近监视器的时候才能观察到。
毛刺效果。屏幕会周期性故障,改变像素的分辨率和颜色。
这篇教程将介绍前三个方面。要注意很重要的一点是,在真实的LCD监视器中是没有放大效果的。这是因为完整图像确实是由小的RGB单元组成的。但在着色器中不会这样。如果没有特定的代码处理,一个简单的LCD渲染从远处看时会产生太多假影。
最后,本文将基于Unity中标准的表面着色器来实现该特效。大家也可以在此基础上加入其它效果,如反射和散射等。
该特效的第一部分由一个简单的像素化着色器实现。方法是在对纹理进行采样前先将UV值约束到一定范围以内。首先添加一个属性用来表示显示器的像素数量。
接下来的代码是获取UV值,0到1之间的连续值,并将它们映射到_Pixels范围内。
结果如下所示:
值得注意的是,这并不是像素化图片以达到LCD显示效果的最好方法。变量_Pixels表示多少像素会显示在原始网格中,而忽略了真实世界的大小。如果缩放了包含上图纹理的四边形,像素的数量依旧不会改变。这与我们希望实现的效果不一致。但只要不调整监视器的尺寸,就没问题。
LCD渲染看起来是个非常复杂的部分,但实际上却很简单。为了达到这个效果,我们需要用一些LCD像素纹理来替换图像的每个像素。谷歌搜索“LCD pixels”就可以找到《Slime Rancher》游戏中实现该效果用到的原图。
从理论上来说,我们只需要单一的RGB单元。为了避免重复,可以使用包含多个单元的一个纹理;这也能让着色器表现得更具多样性。
通过将UV乘以_Pixels可以确保采样的LCD纹理匹配所有像素点。变量_LCDPixels表示有多少RGB单元出现在图片中。
下面要做的就是混合两张图像:
你会发现放大的效果很差,这将在下面的步骤中改善。
当我们靠近监视器的时候应该就能看见LCD特效。远处的观众只能看到像素化的版本。更严谨来讲,如果与相机的距离较近为_DistanceOne,就可以看到完全的LCD效果,如果与相机的距离较远为_DistanceZero,就只能看到像素化效果。所有其它值都是这两个效果之间的线性插值。为了实现这个效果,我们还需要两个附加信息:相机的位置和当前绘制片段的位置。后者可以通过改变输入结构体来获取:
相机位置则始终可以从内置变量_WorldSpaceCameraPos中获取。
下面的代码计算对象与相机间的距离,将其正规化在0和1之间,并用它作为混合系数。
最终效果如下:
本教程为使用着色器来实现现实中LCD显示器的效果打开了良好的思路。如你所见,它与游戏《Slime Rancher》中的效果根本没有可比性。当涉及到着色器时,细节决定成败是不变的真理。很多细节都能显著改善其效果。例如,非线性的缩放曲线,不同的颜色混合函数,增加一些噪声让颜色振荡,等等。如果有什么想法,欢迎来下方评论区分享。
本文来源于:alanzucconi.com
原作者:Alan Zucconi
近期Unity官方将在上海举办官方教育培训活动,为参会者提供系统的Unity技能培训,梳理Unity相关的整个技能树以更好的应用到教学中。
如果您是院校老师(点击活动名称报名):
欢迎参与:Unity官方教育培训
活动时间:6月14日 - 6月16日
活动地点:上海
我们还会分享更多Unity相关的教程在Unity官方中文论坛(forum.china.unity3d.com),请保持关注!